package urora

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

var AllPlatform []string

func init() {
	AllPlatform = []string{"ios","android"}
}
type PushV3 struct {
	Cid string `json:"cid,omitempty"`
	Platform []string `json:"platform"`
	Audience Audience `json:"audience,omitempty"`
	Notification Noification `json:"notification"`
	Message Message `json:"message,omitempty"`
	Options Options `json:"options"`
	CallBack CallBack `json:"callback,omitempty"`
	conf *Config
}

func NewPushV3(config *Config,platform []string) *PushV3 {
	pvs := &PushV3{
		conf: config,
	}
	if platform == nil {
		platform = AllPlatform
	}
	pvs.SetPlatform(platform)
	notify := Noification{}
	pvs.SetNotification(notify)
	return pvs
}

type Audience struct {
	Tag []string `json:"tag,omitempty"`
	Alias []string `json:"alias,omitempty"`
}
type Noification struct {
	Android Android `json:"android,omitempty"`
	IOS IOS `json:"ios,omitempty"`
}
type Android struct {
	Alert string `json:"alert"`
	Title string `json:"title"`
	BuilderId int `json:"builder_id,omitempty"`
	Large_icon string `json:"large_icon,omitempty"`
	Intent Intent `json:"intent,omitempty"`
	Extras Extras `json:"extras,omitempty"`
}
type Intent struct {
	Url string `json:"url"`
}
type Extras struct {
	Newsid int `json:"newsid,omitempty"`
	Type string `json:"type,omitempty""`
	Url string `json:"url"`
}
type IOS struct {
	Alert string `json:"alert"`
	Body string `json:"body"`
	Title string `json:"title"`
	Sound string `json:"sound,omitempty"`
	Badge string `json:"badge,omitempty"`
	threadId string `json:"thread_id,omitempty"`
	Extras Extras `json:"extras,omitempty"`
	ContentAvailable bool `json:"contentA-vailable,omitempty"`
	Category string `json:"category,omitempty"`
}

type Message struct {
	MsgContent string `json:"msg_content"`
	ContentType string `json:"content_type"`
	Title string `json:"title"`
	Extras map[string]string `json:"extras,omitempty"`
}
type Options struct {
	TimeToLive int `json:"time_to_live,omitempty"`
	ApnsProduction bool `json:"apns_production"`
	ApnsCollapseId string `json:"apns_collapse_id,omitempty"`
}

type CallBack struct {
	Url string `json:"url,omitempty"`
	Params map[string]string `json:"params,omitempty"`
	Type int `json:"type,omitempty"`
}

func (p *PushV3) SetPlatform(platform []string)  {
	p.Platform = platform
}
func (p *PushV3) SetAudience(audience Audience)  {
	p.Audience = audience
}
func (p *PushV3) SetNotification(notify Noification)  {
	p.Notification = notify
}
func (p *PushV3) SetMessage(message Message)  {
	p.Message = message
}
func (p *PushV3) SetOption(opt Options)  {
	p.Options = opt
}
func (p *PushV3) SetCallBack(callback CallBack)  {
	p.CallBack = callback
}
func (p *PushV3) NotificationWithAndroid(android Android)  {
	p.Notification.Android = android
}
func (p *PushV3) NotificationWithIOS(ios IOS)  {
	p.Notification.IOS = ios
}
func (p *PushV3) SetCid(cid string)  {
	p.Cid = cid
}
func (p *PushV3) encode() ([]byte,error) {
	data, err := json.Marshal(p)
	return data,err
}
func (p *PushV3) Send() (msgId string,err error) {
	client := http.Client{
		Timeout: time.Second * 3,
	}
	data,err := p.encode()
	if err != nil {
		return
	}
	url := "https://api.jpush.cn/v3/push"
	req,err := http.NewRequest("POST",url,strings.NewReader(string(data)))
	req.SetBasicAuth(p.conf.AppKey,p.conf.Secret)
	headers := map[string]string{
		"Content-Type": "application/json; charset=utf-8",
		"Accept":"application/json",
	}
	for key, header := range headers {
		req.Header.Set(key, header)
	}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	type pushResult struct {
		MsgId string `json:"msg_id"`
		Error struct{
			Code int `json:"code"`
			Message	string `json:"message"`
		}
	}
	var result pushResult
	if err = json.Unmarshal(body, &result); err != nil {
		return
	}
	if result.Error.Code>0 {
		err = fmt.Errorf("code:%d,msg:%s",result.Error.Code,result.Error.Message)
		return
	}
	msgId = result.MsgId
	return
}